public class PriorityQueue {
    private int[] elem; // 存储堆元素的数组
    private int usedSize; // 记录当前堆中元素个数
    private static final int DEFAULT_CAPACITY = 10; // 默认初始容量

    public PriorityQueue() {
        this.elem = new int[DEFAULT_CAPACITY];
        this.usedSize = 0;
    }

    /**
     * 建堆：从最后一个非叶子节点开始向下调整
     * 时间复杂度：O(n)
     * @param array 传入的无序数组
     */
    public void createHeap(int[] array) {
        if (array == null || array.length == 0) return;
        this.elem = new int[array.length];
        System.arraycopy(array, 0, this.elem, 0, array.length);
        this.usedSize = array.length;
        for (int i = (usedSize - 2) / 2; i >= 0; i--) {
            shiftDown(i, usedSize);
        }
    }

    /**
     * 向下调整（维持堆的性质）
     * 时间复杂度：O(log n)
     */
    private void shiftDown(int root, int len) {
        int parent = root;
        int child = 2 * parent + 1; // 左孩子
        while (child < len) {
            // 选择较大的子节点
            if (child + 1 < len && elem[child + 1] > elem[child]) {
                child++;
            }
            if (elem[parent] >= elem[child]) {
                break;
            }
            swap(parent, child);
            parent = child;
            child = 2 * parent + 1;
        }
    }

    /**
     * 插入元素
     * 先插入到数组末尾，然后向上调整
     */
    public void push(int val) {
        if (isFull()) {
            resize();
        }
        elem[usedSize] = val;
        shiftUp(usedSize);
        usedSize++;
    }

    /**
     * 向上调整（插入后保证堆的性质）
     * 时间复杂度：O(log n)
     */
    private void shiftUp(int child) {
        int parent = (child - 1) / 2;
        while (child > 0 && elem[child] > elem[parent]) {
            swap(child, parent);
            child = parent;
            parent = (child - 1) / 2;
        }
    }

    /**
     * 取出堆顶元素（删除最大元素）
     * 用最后一个元素替换堆顶，然后向下调整
     */
    public void pollHeap() {
        if (isEmpty()) {
            throw new RuntimeException("Priority Queue is empty");
        }
        swap(0, usedSize - 1);
        usedSize--;
        shiftDown(0, usedSize);
    }

    /**
     * 获取堆顶元素（最大值）
     */
    public int peekHeap() {
        if (isEmpty()) {
            throw new RuntimeException("Priority Queue is empty");
        }
        return elem[0];
    }

    /**
     * 判断堆是否已满
     */
    public boolean isFull() {
        return usedSize == elem.length;
    }

    /**
     * 判断堆是否为空
     */
    public boolean isEmpty() {
        return usedSize == 0;
    }

    /**
     * 数组扩容（动态扩展）
     */
    private void resize() {
        int newCapacity = elem.length * 2;
        int[] newArray = new int[newCapacity];
        System.arraycopy(elem, 0, newArray, 0, elem.length);
        elem = newArray;
    }

    /**
     * 交换数组中两个元素
     */
    private void swap(int i, int j) {
        int temp = elem[i];
        elem[i] = elem[j];
        elem[j] = temp;
    }
}
